package cc.rengu.redp.system.service.impl;

import cc.rengu.redp.base.service.CacheService;
import cc.rengu.redp.common.domain.QueryRequest;
import cc.rengu.redp.common.domain.RedpConstant;
import cc.rengu.redp.common.properties.RedpProperties;
import cc.rengu.redp.common.utils.HashUtil;
import cc.rengu.redp.common.utils.SortUtil;
import cc.rengu.redp.flowable.service.SysWorkFlowService;
import cc.rengu.redp.system.dao.UserMapper;
import cc.rengu.redp.system.dao.UserRoleMapper;
import cc.rengu.redp.system.domain.*;
import cc.rengu.redp.system.manager.UserManager;
import cc.rengu.redp.system.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service("userService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UserConfigService userConfigService;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UserManager userManager;
    @Autowired
    private SysWorkFlowService sysWorkFlowService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private DeptService deptService;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private RedpProperties redpProperties;


    @Override
    public User findByName(String username) {
        return baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
    }

    @Override
    public User findById(String userId) {
        return baseMapper.selectById(Long.valueOf(userId));
    }

    @Override
    public IPage<User> findUserDetail(User user, QueryRequest request) {

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(User::getCreateTime);
        Page<User> page = new Page<>();
        SortUtil.handlePageSort(request, page, "userId", RedpConstant.ORDER_ASC, true);
        try {
            IPage<User> userIPage = this.page(page, queryWrapper);
            List<User> userList = userIPage.getRecords();
            userList.forEach(userItem -> {
                //部门
                if (userItem.getDeptId() != null) {
                    Dept dept = deptService.getById(userItem.getDeptId());
                    if (dept != null) {
                        userItem.setDeptName(dept.getDeptName());
                    }
                }

                //机构
                if (userItem.getOrgId() != null) {
                    Organization organization = organizationService.getById(userItem.getOrgId());
                    if (organization != null) {
                        userItem.setOrgName(organization.getOrgName());
                    }
                }

                //角色
                List<UserRole> userRoles = userRoleService.list(new LambdaQueryWrapper<UserRole>()
                        .eq(UserRole::getUserId, userItem.getUserId()));
                List<String> roleIds = userRoles.stream().map(it ->String.valueOf(it.getRoleId())).collect(Collectors.toList());
                List<Role> roles = roleService.list(new LambdaQueryWrapper<Role>().in(Role::getRoleId, roleIds));
                List<String> roleNames = roles.stream().map(Role::getRoleName).collect(Collectors.toList());
                userItem.setRoleId(String.join(",", roleIds));
                userItem.setRoleName(String.join(",", roleNames));
            });
            return userIPage;
        } catch (Exception e) {
            log.error("查询用户异常", e);
            return null;
        }
    }

    public User findDetail(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        try {
            User user = this.getOne(queryWrapper);
            if (user != null) {
                //部门
                if (user.getDeptId() != null) {
                    Dept dept = deptService.getById(user.getDeptId());
                    if (dept != null) {
                        user.setDeptName(dept.getDeptName());
                    }
                }

                //机构
                if (user.getOrgId() != null) {
                    Organization organization = organizationService.getById(user.getOrgId());
                    if (organization != null) {
                        user.setOrgName(organization.getOrgName());
                        user.setOrgCode(organization.getOrgCode());
                        user.setOrgChain(organization.getOrgChain());
                    }
                }

                //角色
                List<UserRole> userRoles = userRoleService.list(new LambdaQueryWrapper<UserRole>()
                        .eq(UserRole::getUserId, user.getUserId()));
                List<String> roleIds = userRoles.stream().map(it -> String.valueOf(it.getRoleId())).collect(Collectors.toList());
                List<Role> roles = roleService.list(new LambdaQueryWrapper<Role>().in(
                        Role::getRoleId,
                        userRoles.stream().map(it -> it.getRoleId()).collect(Collectors.toList())));
                List<String> roleNames = roles.stream().map(Role::getRoleName).collect(Collectors.toList());
                user.setRoleId(String.join(",", roleIds));
                user.setRoleName(String.join(",", roleNames));
            }
            return user;
        } catch (Exception e) {
            log.error("查询用户异常", e);
            return null;
        }
    }

    @Override
    @Transactional
    public void updateLoginTime(String username) throws Exception {
        User user = new User();
        user.setLastLoginTime(new Date());

        this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getUsername, username));

        // 重新将用户信息加载到 redis中
        cacheService.saveUser(username);
    }

    @Override
    @Transactional
    public void createUser(User user) throws Exception {
        // 创建用户
        user.setCreateTime(new Date());
        user.setAvatar(User.DEFAULT_AVATAR);
        user.setUsername(user.getUsername().trim());
        user.setPassword(HashUtil.encryptGm(user.getUsername(), redpProperties.getDefaultPassword()));
        save(user);

        // 保存用户角色
        String[] roles = user.getRoleId().split(StringPool.COMMA);
        setUserRoles(user, roles);

        // 创建用户默认的个性化配置
        userConfigService.initDefaultUserConfig(String.valueOf(user.getUserId()));

        // 将用户相关信息保存到 Redis中
        userManager.loadUserRedisCache(user);

        // 同步流程引擎
        sysWorkFlowService.saveUser(user.getUsername());
        List<String> roleList = new ArrayList<>();
        for (String id : roles) {
            roleList.add(roleService.findById(id).getRoleName());
        }
        sysWorkFlowService.createMembership(user.getUsername(), roleList);
    }

    @Override
    @Transactional
    public void updateUser(User user) throws Exception {
        // 更新用户
        user.setPassword(null);
        user.setModifyTime(new Date());
        updateById(user);

        //超级管理员禁止更新角色
        if (!user.getUserId().toString().equals(User.ADMIN_USER_ID)) {
            userRoleMapper.delete(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, user.getUserId()));

            String[] roles = user.getRoleId().split(StringPool.COMMA);
            setUserRoles(user, roles);

            // 同步流程引擎
            List<String> roleList = new ArrayList<>();
            for (String id : roles) {
                roleList.add(roleService.findById(id).getRoleName());
            }
            sysWorkFlowService.createMembership(user.getUsername(), roleList);
        }

        // 重新将用户信息，用户角色信息，用户权限信息 加载到 redis中
        cacheService.saveUser(user.getUsername());
        cacheService.saveRoles(user.getUsername());
        cacheService.savePermissions(user.getUsername());
    }

    @Override
    @Transactional
    public void deleteUsers(String[] userIds) throws Exception {
        List<String> list = new ArrayList<>(Arrays.asList(userIds));
        list.remove(User.ADMIN_USER_ID);

        if (list.size() <= 0) return;

        String[] newUserIds = list.toArray(new String[list.size()]);

        // 同步流程引擎
        for (String userId : newUserIds) {
            User user = this.findById(userId);
            this.sysWorkFlowService.deleteUser(user.getUsername());
        }

        // 先删除相应的缓存
        this.userManager.deleteUserRedisCache(newUserIds);

        removeByIds(list);

        // 删除用户角色
        this.userRoleService.deleteUserRolesByUserId(newUserIds);
        // 删除用户个性化配置
        this.userConfigService.deleteByUserId(newUserIds);
    }

    @Override
    @Transactional
    public void updateProfile(User user) throws Exception {
        updateById(user);
        // 重新缓存用户信息
        cacheService.saveUser(user.getUsername());
    }

    @Override
    @Transactional
    public void updateAvatar(String username, String avatar) throws Exception {
        User user = new User();
        user.setAvatar(avatar);

        this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        // 重新缓存用户信息
        cacheService.saveUser(username);
    }

    @Override
    @Transactional
    public void updatePassword(String username, String password) throws Exception {
        User user = new User();
        user.setPassword(HashUtil.encryptGm(username, password));

        this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        // 重新缓存用户信息
        cacheService.saveUser(username);
    }

    @Override
    @Deprecated
    @Transactional
    public void regist(String username, String password) throws Exception {
        User user = new User();
        user.setPassword(HashUtil.encryptGm(username, password));
        user.setUsername(username);
        user.setCreateTime(new Date());
        user.setStatus(User.STATUS_VALID);
        user.setSsex(User.SEX_UNKNOW);
        user.setAvatar(User.DEFAULT_AVATAR);
        user.setDescription("注册用户");
        this.save(user);

        UserRole ur = new UserRole();
        ur.setUserId(user.getUserId());
        ur.setRoleId(2L); // 注册用户角色 ID
        this.userRoleMapper.insert(ur);

        // 创建用户默认的个性化配置
        userConfigService.initDefaultUserConfig(String.valueOf(user.getUserId()));
        // 将用户相关信息保存到 Redis中
        userManager.loadUserRedisCache(user);

    }

    @Override
    @Transactional
    public void resetPassword(String[] usernames) throws Exception {
        for (String username : usernames) {

            User user = new User();
            user.setPassword(HashUtil.encryptGm(username, redpProperties.getDefaultPassword()));

            this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getUsername, username));
            // 重新将用户信息加载到 redis中
            cacheService.saveUser(username);
        }

    }

    @Override
    public List<User> getAllUsers() {
        return this.baseMapper.selectList(new QueryWrapper<>());
    }

    private void setUserRoles(User user, String[] roles) {
        Arrays.stream(roles).forEach(roleId -> {
            UserRole ur = new UserRole();
            ur.setUserId(user.getUserId());
            ur.setRoleId(Long.valueOf(roleId));
            this.userRoleMapper.insert(ur);
        });
    }
}
